package com.guli.secKill.schedule;
/*
 * @Author 罗俊
 * @date 2020/11/30 - 1:35 下午
 *
 */

import com.guli.common.constant.SecKillConstant;
import com.guli.secKill.service.UploadSecKillSkuService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 上架秒杀商品
 * 每天晚上三点；上架最近三天需要秒杀的商品
 * 当天 00:00:00 - 23:59:59 （当天的凌晨三点上架，当天需要上架的商品其实已经在昨天就已经上架完成了，重复上架无需处理）
 * 明天 00:00:00 - 23:59:59
 * 后天 00:00:00 - 23:59:59
 * */
@Service
@Slf4j
public class SecKillSkuScheduled {

    @Resource
    RedissonClient redissonClient;

    @Resource
    UploadSecKillSkuService uploadSecKillSkuService;

    /**
     * 秒杀系统的幂等性问题
     * 使用分布式锁来解决
     * 分布式锁，锁的业务执行完成，状态已经更新完成，释放锁以后，其他人获取到锁，就会拿到最新的状态
     */
    @Scheduled(cron = "0 0 * * * ?")
    @Async
    public void uploadSkuToRedis(){

        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock(SecKillConstant.UPLOAD_SKU_LOCK);

        RLock rLock = readWriteLock.writeLock();
        rLock.lock(10, TimeUnit.SECONDS);

        log.info("现在执行定时任务的上架秒杀商品和秒杀信息，以及秒杀信号量的操作");
        try {
            uploadSecKillSkuService.uploadSkuToRedis(SecKillConstant.PRE_UPLOAD_DAYS);

        }finally {
            rLock.unlock();
        }
    }
}
